package aorm

import (
	"fmt"
	"strings"
)

type generator func(values ...interface{}) (string, []interface{}) //生成器

var generators map[Type]generator  //存放生成器的容器


func init() {
	generators = make(map[Type]generator)
	generators[Insert] = insert
	generators[Values] = values
	generators[Select] = selects
	generators[Limit] =  limit
	generators[Where] =  where
	generators[OrderBy] = orderBy
	generators[Update] = update
	generators[Delete] = deleter
	generators[Count] =  count
}

// 生成 ？例如 : Values(?,?,?...)
func genBindVars(num int )string {
	var vars []string
	for i := 0; i < num; i++ {
		vars = append(vars,"?")
	}
	return strings.Join(vars,", ") //返回 (?, ?, ?, ...)
}

// INSERT INTO $tableName ($fields)
func insert(values ...interface{})(string, []interface{}) {
	tableName := values[0]
	fields := strings.Join(values[1].([]string),",")
	return fmt.Sprintf("INSERT INTO %s (%v)",tableName,fields),values[2:]
}

// VALUES ($v1), ($v2), ...
func values(values ...interface{}) (string, []interface{}) {
	var (
		bindStr string
		sql strings.Builder
		vars []interface{}
	)
	sql.WriteString("VALUES ")
	for i, value := range values {

		v := value.([]interface{})
		if bindStr == "" {
			bindStr = genBindVars(len(v))
		}
		sql.WriteString(fmt.Sprintf("(%v)", bindStr))
		if i+1 != len(values) {
			sql.WriteString(", ")
		}
		vars = append(vars, v...)
	}
	return sql.String(), vars
}

// SELECT $fields FROM $tableName
func selects (values ...interface{})(string, []interface{}) {
	tableName := values[0]
	fields := strings.Join(values[1].([]string),",")
	return fmt.Sprintf("SELECT %v FROM %s", fields, tableName),values[2:]
}

// LIMIT $num
func limit (values ...interface{})(string,[]interface{}) {
	return "LIMIT ?", values
}

// WHERE $desc
func  where (values ...interface{})(string,[]interface{}) {
	desc, vars := values[0],values[1:]
	return fmt.Sprintf("WHERE %s", desc), vars
}

func orderBy (values ...interface{})(string,[]interface{}) {
	return fmt.Sprintf("ORDER BY %s", values[0]), values[1:]
}

// update 设计入参是2个，第一个参数是表名(table)，第二个参数是 map 类型，表示待更新的键值对。
func update(values ...interface{}) (string, []interface{}) {
	tableName := values[0]
	m := values[1].(map[string]interface{})
	var keys []string
	var vars []interface{}
	for k, v := range m {
		keys = append(keys, k+" = ?")
		vars = append(vars, v)
	}
	return fmt.Sprintf("UPDATE %s SET %s", tableName, strings.Join(keys, ", ")), vars
}

// deleter 只有一个入参，即表名。
func deleter(values ...interface{}) (string, []interface{}) {
	return fmt.Sprintf("DELETE FROM %s", values[0]), []interface{}{}
}

// count 只有一个入参，即表名
func count(values ...interface{}) (string, []interface{}) {
	return selects(values[0], []string{"count(*)"})
}
